#include "mediastreamer2/devices.h"

#include "../../videofilters/h26x/h26x-encoder-filter.h"
#include "filter-wrapper/encoding-filter-wrapper.h"
#include "ohos_video_h264_encoder.h"
#include <multimedia/player_framework/native_avcodec_base.h>

#define MS_MEDIACODECH265_CONF(required_bitrate, bitrate_limit, resolution, fps, ncpus)                                \
	{                                                                                                                  \
		required_bitrate, bitrate_limit, {MS_VIDEO_SIZE_##resolution##_W, MS_VIDEO_SIZE_##resolution##_H}, fps, ncpus, \
		    nullptr                                                                                                    \
	}

static const MSVideoConfiguration video_codec_h264_conf_list[] = {
/*
 * Formats above 720P are disabled. Indeed, there are not supported in baseline profile of H264, and it was observed
 * that when we ask a MediaCodec to output a 1080P stream with baseline profile, we get interoperability issues:
 * the remote decoder decodes it improperly, even on iOS.
 * TODO: enable use of higher profiles to use formats above 720P.
 */
#if 0
	MS_MEDIACODECH265_CONF(2048000, 5000000,       UXGA, 25,  2),
	MS_MEDIACODECH265_CONF(1500000, 3000000, SXGA_MINUS, 25,  2),
#endif
    MS_MEDIACODECH265_CONF(1024000, 2048000, 720P, 30, 2), MS_MEDIACODECH265_CONF(850000, 2048000, XGA, 25, 2),
    MS_MEDIACODECH265_CONF(750000, 1500000, SVGA, 30, 2),  MS_MEDIACODECH265_CONF(600000, 3000000, VGA, 30, 2),
    MS_MEDIACODECH265_CONF(400000, 800000, VGA, 15, 2),    MS_MEDIACODECH265_CONF(128000, 512000, CIF, 15, 1),
    MS_MEDIACODECH265_CONF(100000, 380000, QVGA, 15, 1),   MS_MEDIACODECH265_CONF(0, 170000, QCIF, 10, 1),
};

namespace mediastreamer {

class OHOSVideoEncoder : public OHOSMediaEncode {
public:
	OHOSVideoEncoder() : OHOSMediaEncode("video/avc") {
	}

private:
	OH_AVFormat *createMediaFormat() const override {
		OH_AVFormat *format = OHOSMediaEncode::createMediaFormat();
		OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, _profile);
		OH_AVFormat_SetIntValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, _level);
		return format;
	}

	static const int32_t _profile = 1; // AVCProfileBaseline
	static const int32_t _level = 512; // AVCLevel31
};

class OHOSVideoEncoderFilterImpl : public H26xEncoderFilter {
public:
	OHOSVideoEncoderFilterImpl(MSFilter *f) : H26xEncoderFilter(f, new OHOSVideoEncoder(), video_codec_h264_conf_list) {
		SoundDeviceDescription *info = ms_devices_info_get_sound_device_description(f->factory->devices_info);
		auto &encoder = static_cast<OHOSMediaEncode &>(*_encoder);
		encoder.enablePixelFormatConversion((info->flags & DEVICE_MCH264ENC_NO_PIX_FMT_CONV) == 0);
	}
};

} // namespace mediastreamer

using namespace mediastreamer;

MS_ENCODING_FILTER_WRAPPER_METHODS_DECLARATION(OHOSVideoEncoder);
MS_ENCODING_FILTER_WRAPPER_DESCRIPTION_DECLARATION(OHOSVideoEncoder,
                                                   MS_OHOS_VIDEO_ENC,
                                                   "ohos video h264 encoder ",
                                                   "H264",
                                                   MS_FILTER_IS_PUMP | MS_FILTER_IS_HW_ACCELERATED);

MS_FILTER_DESC_EXPORT(ms_OHOSVideoEncoder_desc)